#!/usr/bin/env fbpython
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is dual-licensed under either the MIT license found in the
# LICENSE-MIT file in the root directory of this source tree or the Apache
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
# of this source tree. You may select, at your option, one of the
# above-listed licenses.

import unittest

from cxx.dist_lto.tools.dist_lto_opt_gnu import _filter_flags


class TestDistLtoOpt(unittest.TestCase):
    def test_filter_flags(self):
        inputs = [
            "-not-opt-flag",
            "-Wl,-plugin-opt,-llvm_flag1",
            "-Wl,-plugin-opt=-llvm_flag1_different_format",
            "-Wl,-plugin-opt,sample-profile=/fbcode/abc/autofdo.profile",
            "-Wl,--lto-whole-program-visibility",
            "-Wl,-mllvm,-llvm-flag2",
            "-Wl,-plugin-opt,O3",
            "-Wl,-plugin-opt,-function-sections",
            "-Wl,-mllvm,-hot-callsite-threshold=12000",
            "-shared",
        ]
        flags = _filter_flags(inputs)
        self.assertListEqual(
            flags,
            [
                "-O2",
                "-ffunction-sections",
                "-fdata-sections",
                "-mllvm",
                "-llvm_flag1",
                "-mllvm",
                "-llvm_flag1_different_format",
                "-fprofile-sample-use=/fbcode/abc/autofdo.profile",
                "-mllvm",
                "-llvm-flag2",
                "-O3",
                "-mllvm",
                "-hot-callsite-threshold=12000",
                "-fPIC",
            ],
        )

    def test_filter_flags_hhvm_case_rev_0f8618f31(self):
        inputs = [
            "--target=x86_64-redhat-linux-gnu",
            "-nostdinc",
            "-resource-dir",
            "-idirafter",
            "-idirafter",
            "fbcode/third-party-buck/platform010/build/glibc/include",
            "-idirafter",
            "fbcode/third-party-buck/platform010/build/kernel-headers/include",
            "-Bfbcode/third-party-buck/platform010/build/binutils/x86_64-facebook-linux/bin",
            "--cflag=--target=x86_64-redhat-linux-gnu",
            "-Bfbcode/third-party-buck/platform010/build/glibc/lib",
            "-Bfbcode/third-party-buck/platform010/tools/gcc/lib/gcc/x86_64-redhat-linux-gnu/trunk",
            "-Lfbcode/third-party-buck/platform010/build/libgcc/lib/gcc/x86_64-facebook-linux/trunk",
            "-Wl,-nostdlib",
            "-Wl,--dynamic-linker,/usr/local/fbcode/platform010/lib/ld.so",
            "-Wl,--disable-new-dtags",
            "-Bfbcode/third-party-buck/platform010/build/binutils/x86_64-facebook-linux/bin",
            "-Wl,--no-mmap-output-file",
            "-nodefaultlibs",
            "--target=x86_64-redhat-linux-gnu",
            "-Lfbcode/third-party-buck/platform010/build/glibc/lib",
            "-Lfbcode/third-party-buck/platform010/build/libgcc/lib",
            "-Wl,-z,notext",
            "-Wl,-z,relro",
            "-Wl,--gc-sections",
            "-fuse-ld=lld",
            "-Wl,--discard-section=.nv_fatbin",
            "-Wl,--discard-section=.nvFatBinSegment",
            "-Wl,--discard-section=.rela.debug_info",
            "-Wl,--discard-section=.rela.debug_ranges",
            "-Wl,--discard-section=.rela.debug_loc",
            "-Wl,--discard-section=.rela.debug_line",
            "-Wl,--discard-section=.rela.debug_aranges",
            "-Wl,--discard-section=.rela.debug_types",
            "-Wl,-O1",
            "-Wl,--build-id=sha1",
            "-Wl,-mllvm,-hot-callsite-threshold=12000",
            "-Wl,--lto-whole-program-visibility",
            "-fwhole-program-vtables",
            "-Wl,--no-discard-section=.nv_fatbin",
            "-Wl,--no-discard-section=.nvFatBinSegment",
            "fbcode/tools/build/move_gpu_sections_implicit_linker_script.txt",
            "-fuse-ld=lld",
            "--build-info=full",
            "--build-info-build-mode=opt-hhvm-lto",
            "--build-info-build-tool=buck2",
            "--build-info-compiler=clang",
            "--build-info-fdo-profile=",
            "--build-info-platform=platform010",
            "--build-info-rule=fbcode:scripts/fnz/minimal:minimal",
            "--build-info-rule-type=cpp_binary",
            "-flto=thin",
            "-Wl,-plugin-opt,-function-sections",
            "-Wl,-plugin-opt,-profile-guided-section-prefix=false",
            "-Wl,-plugin-opt,-generate-type-units",
            "-Wl,-plugin-opt,-enable-lto-ir-verification=false",
            "-Xlinker",
            "--export-dynamic-symbol=mallocx",
            "-Xlinker",
            "--export-dynamic-symbol=rallocx",
            "-Xlinker",
            "--export-dynamic-symbol=xallocx",
            "-Xlinker",
            "--export-dynamic-symbol=sallocx",
            "-Xlinker",
            "--export-dynamic-symbol=dallocx",
            "-Xlinker",
            "--export-dynamic-symbol=sdallocx",
            "-Xlinker",
            "--export-dynamic-symbol=nallocx",
            "-Xlinker",
            "--export-dynamic-symbol=mallctl",
            "-Xlinker",
            "--export-dynamic-symbol=mallctlnametomib",
            "-Xlinker",
            "--export-dynamic-symbol=mallctlbymib",
            "-Xlinker",
            "--export-dynamic-symbol=malloc_stats_print",
            "-Xlinker",
            "--export-dynamic-symbol=malloc_usable_size",
            "-Xlinker",
            "--export-dynamic-symbol=malloc_message",
        ]
        flags = _filter_flags(inputs)
        self.assertIsNotNone(flags)
        self.assertListEqual(
            flags,
            [
                "-O2",
                "-ffunction-sections",
                "-fdata-sections",
                "-fuse-ld=lld",
                "-mllvm",
                "-hot-callsite-threshold=12000",
                "-fwhole-program-vtables",
                "-fuse-ld=lld",
                "-mllvm",
                "-profile-guided-section-prefix=false",
                "-mllvm",
                "-generate-type-units",
                "-mllvm",
                "-enable-lto-ir-verification=false",
            ],
        )

    def test_filter_flags_unicorn_case_rev_0f8618f31(self):
        inputs = [
            "--cflag=--target=x86_64-redhat-linux-gnu",
            "-Bfbcode/third-party-buck/platform010/build/glibc/lib",
            "-Bfbcode/third-party-buck/platform010/tools/gcc/lib/gcc/x86_64-redhat-linux-gnu/trunk",
            "-Lfbcode/third-party-buck/platform010/build/libgcc/lib/gcc/x86_64-facebook-linux/trunk",
            "-Wl,-nostdlib",
            "-Wl,--dynamic-linker,/usr/local/fbcode/platform010/lib/ld.so",
            "-Wl,--disable-new-dtags",
            "-Bfbcode/third-party-buck/platform010/build/binutils/x86_64-facebook-linux/bin",
            "-Wl,--no-mmap-output-file",
            "-nodefaultlibs",
            "--target=x86_64-redhat-linux-gnu",
            "-Lfbcode/third-party-buck/platform010/build/glibc/lib",
            "-Lfbcode/third-party-buck/platform010/build/libgcc/lib",
            "-Wl,-z,notext",
            "-Wl,-z,relro",
            "-Wl,--gc-sections",
            "-fuse-ld=lld",
            "-Wl,--discard-section=.nv_fatbin",
            "-Wl,--discard-section=.nvFatBinSegment",
            "-Wl,--discard-section=.rela.debug_info",
            "-Wl,--discard-section=.rela.debug_ranges",
            "-Wl,--discard-section=.rela.debug_loc",
            "-Wl,--discard-section=.rela.debug_line",
            "-Wl,--discard-section=.rela.debug_aranges",
            "-Wl,--discard-section=.rela.debug_types",
            "-Wl,-O1",
            "-Wl,--build-id=sha1",
            "-Xlinker",
            "-znow",
            "-Xlinker",
            "--emit-relocs",
            "--build-info=full",
            "--build-info-build-mode=opt-clang-thinlto",
            "--build-info-build-tool=buck2",
            "--build-info-compiler=clang",
            "--build-info-fdo-profile=fbcode//fdo/autofdo/default_profile:autofdo",
            "--build-info-platform=platform010",
            "--build-info-rule=fbcode:unicorn:index_server",
            "--build-info-rule-type=cpp_binary",
            "-flto=thin",
            "-Wl,-plugin-opt,sample-profile=buck-out/v2/gen/fbcode/40fc99293b37c503/fdo/autofdo/default_profile/__autofdo__/out/profile",
            "-Wl,-plugin-opt,-function-sections",
            "-Wl,-plugin-opt,-profile-guided-section-prefix=false",
            "-Wl,-plugin-opt,-generate-type-units",
            "-Wl,-plugin-opt,-enable-lto-ir-verification=false",
            "-Xlinker",
            "--push-state",
            "-Xlinker",
            "--no-as-needed",
            "-Xlinker",
            "--pop-state",
            "-Wl,--undefined,Global",
            "-Wl,--undefined,Local",
            "-Wl,--undefined,MockConnection",
            "-Wl,--undefined,Global",
            "-Wl,--undefined,Local",
            "-Wl,--undefined,MockConnection",
            "-Xlinker",
            "--start-group",
            "fbcode/third-party-buck/platform010/build/IntelComposerXE/mkl/lib/intel64/libmkl_intel_lp64.a",
            "fbcode/third-party-buck/platform010/build/IntelComposerXE/mkl/lib/intel64/libmkl_core.a",
            "fbcode/third-party-buck/platform010/build/IntelComposerXE/mkl/lib/intel64/libmkl_intel_thread.a",
            "-Xlinker",
            "--end-group",
            "-lpthread",
            "-Xlinker",
            "--export-dynamic-symbol=mallocx",
            "-Xlinker",
            "--export-dynamic-symbol=rallocx",
            "-Xlinker",
            "--export-dynamic-symbol=xallocx",
            "-Xlinker",
            "--export-dynamic-symbol=sallocx",
            "-Xlinker",
            "--export-dynamic-symbol=dallocx",
            "-Xlinker",
            "--export-dynamic-symbol=sdallocx",
            "-Xlinker",
            "--export-dynamic-symbol=nallocx",
            "-Xlinker",
            "--export-dynamic-symbol=mallctl",
            "-Xlinker",
            "--export-dynamic-symbol=mallctlnametomib",
            "-Xlinker",
            "--export-dynamic-symbol=mallctlbymib",
            "-Xlinker",
            "--export-dynamic-symbol=malloc_stats_print",
            "-Xlinker",
            "--export-dynamic-symbol=malloc_usable_size",
            "-Xlinker",
            "--export-dynamic-symbol=malloc_message",
        ]
        flags = _filter_flags(inputs)
        self.assertIsNotNone(flags)
        self.assertListEqual(
            flags,
            [
                "-O2",
                "-ffunction-sections",
                "-fdata-sections",
                "-fuse-ld=lld",
                "-fprofile-sample-use=buck-out/v2/gen/fbcode/40fc99293b37c503/fdo/autofdo/default_profile/__autofdo__/out/profile",
                "-mllvm",
                "-profile-guided-section-prefix=false",
                "-mllvm",
                "-generate-type-units",
                "-mllvm",
                "-enable-lto-ir-verification=false",
            ],
        )
